package top.guoziyang.mydb.backend.dm.dataItem;

import java.util.Arrays;

import com.google.common.primitives.Bytes;

import top.guoziyang.mydb.backend.common.SubArray;
import top.guoziyang.mydb.backend.dm.DataManagerImpl;
import top.guoziyang.mydb.backend.dm.page.Page;
import top.guoziyang.mydb.backend.utils.Parser;
import top.guoziyang.mydb.backend.utils.Types;

public interface DataItem {
    SubArray data();
    
    void before();
    void unBefore();
    void after(long xid);
    void release();

    void lock();
    void unlock();
    void rLock();
    void rUnLock();

    Page page();
    long getUid();
    byte[] getOldRaw();
    SubArray getRaw();

    /**
     * 将数据打包成DataItem格式的字节集群，用于序列化和存储
     */
    public static byte[] wrapDataItemRaw(byte[] raw) {
        byte[] valid = new byte[1];
        byte[] size = Parser.short2Byte((short)raw.length);
        return Bytes.concat(valid, size, raw);
    }

    /**
     * 从页面的特定偏移位置读取数据的长度和内容，将数据封装成DataItemImpl。
     * 由于Page是存储数据的最小单位，整个页面可能包含多个数据项，而页面中的每个数据项都有特定的偏移位置。因此，在访问特定数据时，需要通过偏移量offset定位到具体的数据项。
     */
    public static DataItem parseDataItem(Page pg, short offset, DataManagerImpl dm) {
        // 获取整个页面的数据
        byte[] raw = pg.getData();
        // 从页面的特定偏移量读取一个数据项，获取这个数据项的datasize
        short size = Parser.parseShort(Arrays.copyOfRange(raw, offset+DataItemImpl.OF_SIZE, offset+DataItemImpl.OF_DATA));
        // datasize加上元数据头部([ValidFlag] [DataSize])即为数据项的长度
        short length = (short)(size + DataItemImpl.OF_DATA);
        //将页面号和偏移量组合生成一个唯一标识符uid
        long uid = Types.addressToUid(pg.getPageNumber(), offset);
        // 最终返回DataItemImpl，这是一个包含完整数据信息的数据项对象
        return new DataItemImpl(new SubArray(raw, offset, offset+length), new byte[length], pg, uid, dm);
    }

    /**
     * 把dataItem设为非法
     */
    public static void setDataItemRawInvalid(byte[] raw) {
        // 0为合法，1为非法
        raw[DataItemImpl.OF_VALID] = (byte)1;
    }
}
